#include "ofApp.h"

bool compareName( const colorNameMapping& s1, const colorNameMapping& s2 ) {
	return s1.name < s2.name;
}

bool compareBrightness( const colorNameMapping& s1, const colorNameMapping& s2 ) {
	return s1.color.getBrightness() < s2.color.getBrightness();
}

bool compareHue( const colorNameMapping& s1, const colorNameMapping& s2 ) {
	return s1.color.getHue() < s2.color.getHue();
}

bool compareSaturation( const colorNameMapping& s1, const colorNameMapping& s2 ) {
	return s1.color.getSaturation() < s2.color.getSaturation();
}

//--------------------------------------------------------------
void ofApp::setup(){

	// build a map from name to ofColor of all the named OF colors;

	colorNameMap["white"] = ofColor::white;
	colorNameMap["gray"] = ofColor::gray;
	colorNameMap["black"] = ofColor::black;
	colorNameMap["red"] = ofColor::red;
	colorNameMap["green"] = ofColor::green;
	colorNameMap["blue"] = ofColor::blue;
	colorNameMap["cyan"] = ofColor::cyan;
	colorNameMap["magenta"] = ofColor::magenta;
	colorNameMap["yellow"] = ofColor::yellow;
	colorNameMap["aliceBlue"] = ofColor::aliceBlue;
	colorNameMap["antiqueWhite"] = ofColor::antiqueWhite;
	colorNameMap["aqua"] = ofColor::aqua;
	colorNameMap["aquamarine"] = ofColor::aquamarine;
	colorNameMap["azure"] = ofColor::azure;
	colorNameMap["beige"] = ofColor::beige;
	colorNameMap["bisque"] = ofColor::bisque;
	colorNameMap["blanchedAlmond"] = ofColor::blanchedAlmond;
	colorNameMap["blueViolet"] = ofColor::blueViolet;
	colorNameMap["brown"] = ofColor::brown;
	colorNameMap["burlyWood"] = ofColor::burlyWood;
	colorNameMap["cadetBlue"] = ofColor::cadetBlue;
	colorNameMap["chartreuse"] = ofColor::chartreuse;
	colorNameMap["chocolate"] = ofColor::chocolate;
	colorNameMap["coral"] = ofColor::coral;
	colorNameMap["cornflowerBlue"] = ofColor::cornflowerBlue;
	colorNameMap["cornsilk"] = ofColor::cornsilk;
	colorNameMap["crimson"] = ofColor::crimson;
	colorNameMap["darkBlue"] = ofColor::darkBlue;
	colorNameMap["darkCyan"] = ofColor::darkCyan;
	colorNameMap["darkGoldenRod"] = ofColor::darkGoldenRod;
	colorNameMap["darkGray"] = ofColor::darkGray;
	colorNameMap["darkGrey"] = ofColor::darkGrey;
	colorNameMap["darkGreen"] = ofColor::darkGreen;
	colorNameMap["darkKhaki"] = ofColor::darkKhaki;
	colorNameMap["darkMagenta"] = ofColor::darkMagenta;
	colorNameMap["darkOliveGreen"] = ofColor::darkOliveGreen;
	colorNameMap["darkOrange"] = ofColor::darkOrange;
	colorNameMap["darkOrchid"] = ofColor::darkOrchid;
	colorNameMap["darkRed"] = ofColor::darkRed;
	colorNameMap["darkSalmon"] = ofColor::darkSalmon;
	colorNameMap["darkSeaGreen"] = ofColor::darkSeaGreen;
	colorNameMap["darkSlateBlue"] = ofColor::darkSlateBlue;
	colorNameMap["darkSlateGray"] = ofColor::darkSlateGray;
	colorNameMap["darkSlateGrey"] = ofColor::darkSlateGrey;
	colorNameMap["darkTurquoise"] = ofColor::darkTurquoise;
	colorNameMap["darkViolet"] = ofColor::darkViolet;
	colorNameMap["deepPink"] = ofColor::deepPink;
	colorNameMap["deepSkyBlue"] = ofColor::deepSkyBlue;
	colorNameMap["dimGray"] = ofColor::dimGray;
	colorNameMap["dimGrey"] = ofColor::dimGrey;
	colorNameMap["dodgerBlue"] = ofColor::dodgerBlue;
	colorNameMap["fireBrick"] = ofColor::fireBrick;
	colorNameMap["floralWhite"] = ofColor::floralWhite;
	colorNameMap["forestGreen"] = ofColor::forestGreen;
	colorNameMap["fuchsia"] = ofColor::fuchsia;
	colorNameMap["gainsboro"] = ofColor::gainsboro;
	colorNameMap["ghostWhite"] = ofColor::ghostWhite;
	colorNameMap["gold"] = ofColor::gold;
	colorNameMap["goldenRod"] = ofColor::goldenRod;
	colorNameMap["grey"] = ofColor::grey;
	colorNameMap["greenYellow"] = ofColor::greenYellow;
	colorNameMap["honeyDew"] = ofColor::honeyDew;
	colorNameMap["hotPink"] = ofColor::hotPink;
	colorNameMap["indianRed "] = ofColor::indianRed ;
	colorNameMap["indigo "] = ofColor::indigo ;
	colorNameMap["ivory"] = ofColor::ivory;
	colorNameMap["khaki"] = ofColor::khaki;
	colorNameMap["lavender"] = ofColor::lavender;
	colorNameMap["lavenderBlush"] = ofColor::lavenderBlush;
	colorNameMap["lawnGreen"] = ofColor::lawnGreen;
	colorNameMap["lemonChiffon"] = ofColor::lemonChiffon;
	colorNameMap["lightBlue"] = ofColor::lightBlue;
	colorNameMap["lightCoral"] = ofColor::lightCoral;
	colorNameMap["lightCyan"] = ofColor::lightCyan;
	colorNameMap["lightGoldenRodYellow"] = ofColor::lightGoldenRodYellow;
	colorNameMap["lightGray"] = ofColor::lightGray;
	colorNameMap["lightGrey"] = ofColor::lightGrey;
	colorNameMap["lightGreen"] = ofColor::lightGreen;
	colorNameMap["lightPink"] = ofColor::lightPink;
	colorNameMap["lightSalmon"] = ofColor::lightSalmon;
	colorNameMap["lightSeaGreen"] = ofColor::lightSeaGreen;
	colorNameMap["lightSkyBlue"] = ofColor::lightSkyBlue;
	colorNameMap["lightSlateGray"] = ofColor::lightSlateGray;
	colorNameMap["lightSlateGrey"] = ofColor::lightSlateGrey;
	colorNameMap["lightSteelBlue"] = ofColor::lightSteelBlue;
	colorNameMap["lightYellow"] = ofColor::lightYellow;
	colorNameMap["lime"] = ofColor::lime;
	colorNameMap["limeGreen"] = ofColor::limeGreen;
	colorNameMap["linen"] = ofColor::linen;
	colorNameMap["maroon"] = ofColor::maroon;
	colorNameMap["mediumAquaMarine"] = ofColor::mediumAquaMarine;
	colorNameMap["mediumBlue"] = ofColor::mediumBlue;
	colorNameMap["mediumOrchid"] = ofColor::mediumOrchid;
	colorNameMap["mediumPurple"] = ofColor::mediumPurple;
	colorNameMap["mediumSeaGreen"] = ofColor::mediumSeaGreen;
	colorNameMap["mediumSlateBlue"] = ofColor::mediumSlateBlue;
	colorNameMap["mediumSpringGreen"] = ofColor::mediumSpringGreen;
	colorNameMap["mediumTurquoise"] = ofColor::mediumTurquoise;
	colorNameMap["mediumVioletRed"] = ofColor::mediumVioletRed;
	colorNameMap["midnightBlue"] = ofColor::midnightBlue;
	colorNameMap["mintCream"] = ofColor::mintCream;
	colorNameMap["mistyRose"] = ofColor::mistyRose;
	colorNameMap["moccasin"] = ofColor::moccasin;
	colorNameMap["navajoWhite"] = ofColor::navajoWhite;
	colorNameMap["navy"] = ofColor::navy;
	colorNameMap["oldLace"] = ofColor::oldLace;
	colorNameMap["olive"] = ofColor::olive;
	colorNameMap["oliveDrab"] = ofColor::oliveDrab;
	colorNameMap["orange"] = ofColor::orange;
	colorNameMap["orangeRed"] = ofColor::orangeRed;
	colorNameMap["orchid"] = ofColor::orchid;
	colorNameMap["paleGoldenRod"] = ofColor::paleGoldenRod;
	colorNameMap["paleGreen"] = ofColor::paleGreen;
	colorNameMap["paleTurquoise"] = ofColor::paleTurquoise;
	colorNameMap["paleVioletRed"] = ofColor::paleVioletRed;
	colorNameMap["papayaWhip"] = ofColor::papayaWhip;
	colorNameMap["peachPuff"] = ofColor::peachPuff;
	colorNameMap["peru"] = ofColor::peru;
	colorNameMap["pink"] = ofColor::pink;
	colorNameMap["plum"] = ofColor::plum;
	colorNameMap["powderBlue"] = ofColor::powderBlue;
	colorNameMap["purple"] = ofColor::purple;
	colorNameMap["rosyBrown"] = ofColor::rosyBrown;
	colorNameMap["royalBlue"] = ofColor::royalBlue;
	colorNameMap["saddleBrown"] = ofColor::saddleBrown;
	colorNameMap["salmon"] = ofColor::salmon;
	colorNameMap["sandyBrown"] = ofColor::sandyBrown;
	colorNameMap["seaGreen"] = ofColor::seaGreen;
	colorNameMap["seaShell"] = ofColor::seaShell;
	colorNameMap["sienna"] = ofColor::sienna;
	colorNameMap["silver"] = ofColor::silver;
	colorNameMap["skyBlue"] = ofColor::skyBlue;
	colorNameMap["slateBlue"] = ofColor::slateBlue;
	colorNameMap["slateGray"] = ofColor::slateGray;
	colorNameMap["slateGrey"] = ofColor::slateGrey;
	colorNameMap["snow"] = ofColor::snow;
	colorNameMap["springGreen"] = ofColor::springGreen;
	colorNameMap["steelBlue"] = ofColor::steelBlue;
	colorNameMap["tan"] = ofColor::tan;
	colorNameMap["teal"] = ofColor::teal;
	colorNameMap["thistle"] = ofColor::thistle;
	colorNameMap["tomato"] = ofColor::tomato;
	colorNameMap["turquoise"] = ofColor::turquoise;
	colorNameMap["violet"] = ofColor::violet;
	colorNameMap["wheat"] = ofColor::wheat;
	colorNameMap["whiteSmoke"] = ofColor::whiteSmoke;
	colorNameMap["yellowGreen"] = ofColor::yellowGreen;

	// this map is useful if we want to address the colors by string.
	// since we might want to sort this, we can put them in a vector also

	for (unsigned int i = 0; i < colorNameMap.size(); i++){

		map<string, ofColor>::iterator mapEntry = colorNameMap.begin();
		std::advance( mapEntry, i );

		colorNameMapping mapping;
		mapping.name = mapEntry->first;
		mapping.color = mapEntry->second;
		colorNames.push_back(mapping);

	}

	ofBackground(255);

	ofSetVerticalSync(true);

	ofEnableAlphaBlending();


	sortedType = 1; // by name, at the start

}

//--------------------------------------------------------------
void ofApp::update(){

	// smoothing the mouse a bit over time

	mouseSmoothed = 0.95 * mouseSmoothed + 0.05 * glm::vec3(mouseX, mouseY,0);

}

//--------------------------------------------------------------
void ofApp::draw(){

	// calculate the total size needed to display all the colors

	float totalSize = (ceil(colorNameMap.size()/3.0)) * 50 - ofGetHeight() + 60;

	// map the smoothed mouse to this:

	float offset = ofMap(mouseSmoothed.y, 0, ofGetHeight(), 0, totalSize, true);

	// draw all the colors
	// note this could be optimized, since we're drawing plenty that's offscreen here.



	for (unsigned int i = 0; i < colorNames.size(); i++){

		int x = (i % 3) * ofGetWidth()/3.0;
		int y = (floor(i / 3)) * 50;

		ofSetColor( colorNames[i].color );
		ofDrawRectangle(0 + x, y - offset, (i%3 == 2) ? ofGetWidth() - x : ofGetWidth()/3.0, 50);

		ofDrawBitmapStringHighlight(colorNames[i].name, 20 + x, y -offset+30, ofColor::white, ofColor::black);

	}



	ofSetColor(0);
	ofDrawRectangle(0, ofGetHeight()-60, ofGetWidth(), 60);
	ofDrawBitmapStringHighlight("press '1' to sort by name, '2' to sort by hue,\n'3' to sort by brightness, '4' to sort by saturation", 20, ofGetHeight()-60 + 30, ofColor::black, ofColor::white);


}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

	if (key == '1'){
		if (sortedType != 1){
			sortedType = 1;
			ofSort(colorNames, compareName);
		}
	} else if (key == '2'){
		if (sortedType != 2){
			sortedType = 2;
			ofSort(colorNames, compareHue);
		}
	} else if (key == '3'){
		if (sortedType != 3){
			sortedType = 3;
			ofSort(colorNames, compareBrightness);
		}
	} else if (key == '4'){
		if (sortedType != 4){
			sortedType = 4;
			ofSort(colorNames, compareSaturation);
		}
	}
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
